package com.sunda.spmsoversea.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmscommon.feign.IFeignServiceCommon;
import com.sunda.spmsoversea.dto.OverseaDeliveryNoteCompleteDTO;
import com.sunda.spmsoversea.dto.OverseaDeliveryNoteOaDTO;
import com.sunda.spmsoversea.dto.OverseaDeliveryNotePageDTO;
import com.sunda.spmsoversea.dto.OverseaDeliveryNoteSapItemDTO;
import com.sunda.spmsoversea.entity.*;
import com.sunda.spmsoversea.mapper.OverseaDeliveryNoteMapper;
import com.sunda.spmsoversea.service.*;
import com.sunda.spmsuser.entity.SpmsUser;
import feign.FeignException;
import localhost.services.ExtHrmresources.ExtHrmresourcesPortTypeProxy;
import localhost.services.RequestService.RequestServicePortTypeProxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import weaver.soa.workflow.request.*;

import java.rmi.RemoteException;
import java.util.*;

import static com.sunda.spmscommon.constant.OaConstant.BUSINESS_TYPE_OVERSEA_DELIVERY;
import static com.sunda.spmsoversea.constant.CommonConstant.*;
import static com.sunda.spmsoversea.constant.SapConstant.*;
import static com.sunda.spmsoversea.enums.OverseaDeliveryNoteEnum.*;

/**
 * <p>
 * 海外仓交货单表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-10-22
 */
@Slf4j
@Service
public class OverseaDeliveryNoteServiceImpl extends ServiceImpl<OverseaDeliveryNoteMapper, OverseaDeliveryNote> implements IOverseaDeliveryNoteService {

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;

    @Autowired
    IOverseaDeliveryNoteDtlService iOverseaDeliveryNoteDtlService;

    @Autowired
    IOverseaOperateLogService iOverseaOperateLogService;

    @Autowired
    IOverseaPackageListService iOverseaPackageListService;

    @Autowired
    IOverseaPackageListDtlService iOverseaPackageListDtlService;

    @Autowired
    IOverseaPackageListBoxService iOverseaPackageListBoxService;

    @Autowired
    IFormatDataToSapService iFormatDataToSapService;

    @Value("${oa.workflow.id3168}")
    String workflow3168;

    /** 获取交货单表头分页列表 */
    @Override
    public IPage getOverseaDeliveryNote(OverseaDeliveryNotePageDTO overseaDeliveryNotePageDTO) {
        IPage iPage = overseaDeliveryNotePageDTO.getPage();
        List<Map<String, Object>> mapList = this.baseMapper.getOverseaDeliveryNoteIpage(iPage, overseaDeliveryNotePageDTO);
        iPage.setRecords(mapList);
        return iPage;
    }

    /** 获取交货单表头分页列表，PDA多状态查询 */
    @Override
    public IPage getOverseaDeliveryNotePda(OverseaDeliveryNotePageDTO overseaDeliveryNotePageDTO) {
        IPage iPage = overseaDeliveryNotePageDTO.getPage();
        String spmsStatus = overseaDeliveryNotePageDTO.getSpmsStatus();
        if (StringUtils.isEmpty(spmsStatus)){
            return null;
        }
        List<String> spmsStatusList = Arrays.asList(spmsStatus.split(","));
        List<Map<String, Object>> mapList = this.baseMapper.getOverseaDeliveryNoteIpagePda(iPage, overseaDeliveryNotePageDTO, spmsStatusList);
        iPage.setRecords(mapList);
        return iPage;
    }

    /** 根据交货单号获取一条交货单表头信息——仅交货单信息 */
    @Override
    public OverseaDeliveryNote getOverseaDn(String sapDeliveryNote) {
        if (StringUtils.isEmpty(sapDeliveryNote)){
            return null;
        }
        return this.baseMapper.selectOne(new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote));
    }

    /** 根据交货单号获取交货单物料明细信息 */
    @Override
    public List<Map<String, Object>> getOverseaDeliveryNoteItem(String sapDeliveryNote) {
        if (StringUtils.isEmpty(sapDeliveryNote)){
            return null;
        }
        return iOverseaDeliveryNoteDtlService.getDnItems(sapDeliveryNote);
    }

    /** 根据交货单号获取交货单箱码及箱码明细行号信息 */
    @Override
    public List<Map<String, Object>> getOverseaDeliveryNoteBox(String sapDeliveryNote) {
        if (StringUtils.isEmpty(sapDeliveryNote)){
            return null;
        }
        return iOverseaDeliveryNoteDtlService.getDnBoxItems(sapDeliveryNote);
    }

    /** 根据交货单号获取一条交货单表头信息——含装箱单信息 */
    @Override
    public Map<String, Object> getOverseaDnHead(String sapDeliveryNote) {
        if (StringUtils.isEmpty(sapDeliveryNote)){
            return null;
        }
        return this.baseMapper.getOverseaDnHead(sapDeliveryNote);
    }

    /** 根据交货单号、交货单行号获取一行明细数据 */
    @Override
    public OverseaDeliveryNoteDtl getDnDtl(String sapDeliveryNote, String sapDeliveryNoteItem) {
        if (StringUtils.isEmpty(sapDeliveryNote) || StringUtils.isEmpty(sapDeliveryNoteItem)){
            return null;
        }
        QueryWrapper<OverseaDeliveryNoteDtl> queryWrapper = new QueryWrapper<OverseaDeliveryNoteDtl>()
                .eq("SAP_DELIVERY_NOTE", sapDeliveryNote).eq("SAP_DELIVERY_NOTE_ITEM", sapDeliveryNoteItem);
        return iOverseaDeliveryNoteDtlService.getOne(queryWrapper);
    }

    /**
     根据交货单号 sapDeliveryNote 查询交货单每一行物料 实收、多收、少收数量。
     获取交货单关联的所有入库任务，只有入库任务状态为 3, 4, 5 才算是增加了库存的入库任务，才能被认定为已收货；
     入库任务状态(默认0待入库;1入库中;2入库完成;3审批通过;4提交SAP成功;5提交SAP失败;6已撤销;7关闭;)
     返回指定交货单所有行实收数量信息、应收数量信息、多收少收数量等；
     */
    @Override
    public List<Map<String, Object>> getOverseaDnOverOrUnderCharged(String sapDeliveryNote) {
        if (StringUtils.isEmpty(sapDeliveryNote)){
            return null;
        }
        return this.baseMapper.getOverseaDnOverOrUnderCharged(sapDeliveryNote);
    }

    /**
     交货单关联 入库任务状态(默认0待入库;1入库中;2入库完成;3审批通过;4提交SAP成功;5提交SAP失败;6已撤销;7关闭;)
     只有交货单无关联入库任务 或 关联的所有入库任务都处于 4、7 状态才能执行交货单入库完成操作。
     交货单状态如下：
         默认0待到货/SPMS可从SAP更新单据；
         1-收货中/SAP凭证撤销；
         2-入库完成；
         6-收货多收提交SAP失败；
         7-收货多收提交SAP成功；
         8-收货少收提交SAP失败；
         9-收货少收提交SAP成功；
         10-提交SAP完成；
         11-收货完成；
         12-关闭/废单;
     海外收货任务入库完成——状态变化：0-0; 0-2; 1-1; 1-2;
     1.检查数据版本号；
     2.检查数据可操作状态；
     3.没有进行中的入库任务才可执行此操作；
     4.如果存在少收，将少收信息拼接成 实收入库(Z_SPMS_MIGO) 提交SAP，SPMS无库存操作，成功则更新实收损益和 入库凭证 等信息 0-2/1-2；失败记日志 0-0/1-1；
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult overseaWhsInCompleted(OverseaDeliveryNoteCompleteDTO overseaDeliveryNoteCompleteDTO, String userId) {
        try {
            ResponseResult checkCompletedResult = checkDnCompleted(overseaDeliveryNoteCompleteDTO);
            if (checkCompletedResult.getCode() != SUCCESS){
                return checkCompletedResult;
            }
            String sapDeliveryNote = overseaDeliveryNoteCompleteDTO.getSapDeliveryNote();
            QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
            OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);
            /** 判断完成时单据是否存在少收信息， */
            boolean underchargedQty = checkUnderchargedQty(overseaDeliveryNoteCompleteDTO);
            if(underchargedQty){
                JSONObject dataToSap = formatDataToSap(overseaDeliveryNoteCompleteDTO, overseaDeliveryNote, userId);
                log.info("=======dataToSap=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======message=========\n" + message);
                JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
                    String sapVoucherNumber = RETURN_DATA.getJSONArray("IT_MSG").getJSONObject(0).getString("MBLNR");
                    String sapVoucherYear = RETURN_DATA.getJSONArray("IT_MSG").getJSONObject(0).getString("MJAHR");
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_WHS_IN_SUCCESS.getDescZh() + ":" + sapVoucherNumber,
                            OVERSEA_DN_WHS_IN_SUCCESS.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "少收转实收提交SAP入库成功");
                    overseaDeliveryNote.setCostCenter(overseaDeliveryNoteCompleteDTO.getCostCenter());
                    overseaDeliveryNote.setPostingDate(overseaDeliveryNoteCompleteDTO.getPostingDate());
                    overseaDeliveryNote.setSapVoucherNumber(sapVoucherNumber);
                    overseaDeliveryNote.setSapVoucherYear(sapVoucherYear);
                    overseaDeliveryNote.setSpmsStatus(OVERSEA_WHS_IN_DONE.getCode());
                    this.baseMapper.update(overseaDeliveryNote, queryWrapper);
                    updateOverseaDeliveryNoteItem(overseaDeliveryNoteCompleteDTO);

                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_WHS_IN_DONE.getDescZh(), OVERSEA_WHS_IN_DONE.getDescEn(), "");
                    return ResponseResult.success("交货单完成入库提交SAP成功，交货单损益信息更新成功")
                            .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                            .add("overseaDeliveryNoteItem", getOverseaDeliveryNoteItem(sapDeliveryNote));
                } else {
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_WHS_IN_ERROR.getDescZh(),
                            OVERSEA_DN_WHS_IN_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "少收转实收提交SAP入库失败");
                    return ResponseResult.error("交货单完成入库提交SAP错误，交货单损益信息更新失败")
                            .add("sapReturnedMessage", message)
                            .add("dataToSap", dataToSap);
                }
            } else {
                overseaDeliveryNote.setCostCenter(overseaDeliveryNoteCompleteDTO.getCostCenter());
                overseaDeliveryNote.setSpmsStatus(OVERSEA_WHS_IN_DONE.getCode());
                overseaDeliveryNote.setPostingDate(overseaDeliveryNoteCompleteDTO.getPostingDate());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                updateOverseaDeliveryNoteItem(overseaDeliveryNoteCompleteDTO);

                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_WHS_IN_DONE.getDescZh(), OVERSEA_WHS_IN_DONE.getDescEn(), "");

                return ResponseResult.success("交货单损益信息更新成功")
                        .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                        .add("overseaDeliveryNoteItem", getOverseaDeliveryNoteItem(sapDeliveryNote));
            }
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("请求更新错误 Exception").add("error", e.getMessage());
        }
    }

    //状态变化：0-0; 0-2; 1-1; 1-2;
    ResponseResult checkDnCompleted(OverseaDeliveryNoteCompleteDTO overseaDeliveryNoteCompleteDTO){
        if (overseaDeliveryNoteCompleteDTO == null || overseaDeliveryNoteCompleteDTO.getOverseaDeliveryNoteItem() == null){
            return ResponseResult.error("请求参数错误");
        }
        String sapDeliveryNote = overseaDeliveryNoteCompleteDTO.getSapDeliveryNote();
        String postingDate = overseaDeliveryNoteCompleteDTO.getPostingDate();
        if (StringUtils.isEmpty(sapDeliveryNote) || overseaDeliveryNoteCompleteDTO.getDataVersion() == null){
            return ResponseResult.error("请求参数交货单号或数据版本号不能为空");
        }
        if (StringUtils.isEmpty(postingDate) || INVALID_DATE.equals(postingDate)){
            return ResponseResult.error("过账日期不能为空");
        }
        Integer dataVersion = overseaDeliveryNoteCompleteDTO.getDataVersion();
        QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);
        if (overseaDeliveryNote == null){
            return ResponseResult.error("请求交货单不存在");
        }
        if (!dataVersion.equals(overseaDeliveryNote.getDataVersion())){
            return ResponseResult.error("交货单信息已更新请刷新后重试");
        }
        String spmsStatus = overseaDeliveryNote.getSpmsStatus();
        if (!OVERSEA_DN_WAITING.getCode().equals(spmsStatus)
                && !OVERSEA_DN_RECEIVING.getCode().equals(spmsStatus)){
            return ResponseResult.error("交货单当前状态禁止此操作");
        }
        List<OverseaWhsIn> overseaWhsInList = this.baseMapper.getDoingTask(sapDeliveryNote);
        if (overseaWhsInList != null && overseaWhsInList.size() > 0){
            return ResponseResult.error("交货单还有进行中的入库任务，请先完成入库任务");
        }
        return ResponseResult.success();
    }

    boolean checkUnderchargedQty (OverseaDeliveryNoteCompleteDTO overseaDeliveryNoteCompleteDTO){
        List<OverseaDeliveryNoteSapItemDTO> overseaDeliveryNoteItemList = overseaDeliveryNoteCompleteDTO.getOverseaDeliveryNoteItem();
        for (OverseaDeliveryNoteSapItemDTO itemDTO : overseaDeliveryNoteItemList){
            if (itemDTO.getUnderchargedQtyBasicUnit() > 0){
                return true;
            }
        }
        return false;
    }

    JSONObject formatDataToSap(OverseaDeliveryNoteCompleteDTO completeDTO, OverseaDeliveryNote overseaDeliveryNote, String userId){
        JSONObject doc = new JSONObject();

        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());

        Map<String, Object> head = new HashMap<>();
        head.put("xblnr", completeDTO.getSapDeliveryNote());
        head.put("vbelnIm", completeDTO.getSapDeliveryNote());
        head.put("bldat", overseaDeliveryNote.getArrivalDate().replaceAll("-", ""));
        head.put("budat", completeDTO.getPostingDate().replaceAll("-", ""));
        head.put("createdby", userId);
        head.put("bwart", "101");
        head.put("bktxt", overseaDeliveryNote.getRemarks() == null ? "" : overseaDeliveryNote.getRemarks());

        List<Map<String, Object>> items = new ArrayList<>();
        for (OverseaDeliveryNoteSapItemDTO itemDTO : completeDTO.getOverseaDeliveryNoteItem()){
            double underchargedQtyBasicUnit = itemDTO.getUnderchargedQtyBasicUnit();
            if (underchargedQtyBasicUnit > 0){
                String sapDeliveryNote = itemDTO.getSapDeliveryNote();
                String sapDeliveryNoteItem = itemDTO.getSapDeliveryNoteItem();
                OverseaDeliveryNoteDtl overseaDeliveryNoteDtl = iOverseaDeliveryNoteDtlService.getOverseaDeliveryNoteDtl(sapDeliveryNote, sapDeliveryNoteItem);
                Map<String, Object> item = new HashMap<>();
                item.put("vbelnIm", sapDeliveryNote);
                item.put("vbelpIm", sapDeliveryNoteItem);
                item.put("matnr", overseaDeliveryNoteDtl.getMaterialNo());
                item.put("bstmg", String.valueOf(underchargedQtyBasicUnit));
                item.put("bstme", overseaDeliveryNoteDtl.getBasicUnit());
                item.put("werks", overseaDeliveryNote.getActualWerksReceive());
                item.put("lgort", overseaDeliveryNote.getActualWhsLocationCodeReceive());
                item.put("sgtxt", itemDTO.getRemarks() == null ? "" : itemDTO.getRemarks());
                items.add(item);
            }
        }

        REQUEST_DATA.put("Head", head);
        REQUEST_DATA.put("Items", items);
        REQUEST_DATA.put("Operation", "Z_SPMS_MIGO");
        REQUEST_DATA.put("Type", "SPMS_MIGO");
        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        doc.put("REQUEST", REQUEST);
        return doc;
    }

    void updateOverseaDeliveryNoteItem(OverseaDeliveryNoteCompleteDTO overseaDeliveryNoteCompleteDTO){
        List<OverseaDeliveryNoteSapItemDTO> overseaDeliveryNoteItemList = overseaDeliveryNoteCompleteDTO.getOverseaDeliveryNoteItem();
        for (OverseaDeliveryNoteSapItemDTO itemDTO : overseaDeliveryNoteItemList){
            String sapDeliveryNote = itemDTO.getSapDeliveryNote();
            String sapDeliveryNoteItem = itemDTO.getSapDeliveryNoteItem();
            QueryWrapper<OverseaDeliveryNoteDtl> queryWrapper = new QueryWrapper<OverseaDeliveryNoteDtl>()
                    .eq("SAP_DELIVERY_NOTE", sapDeliveryNote).eq("SAP_DELIVERY_NOTE_ITEM", sapDeliveryNoteItem);
            OverseaDeliveryNoteDtl dtl = new OverseaDeliveryNoteDtl();
            dtl.setActualQtyBasicUnit(itemDTO.getActualQtyBasicUnit());
            dtl.setActualQtyUnitSales(itemDTO.getActualQtyUnitSales());
            dtl.setOverchargedQtyBasicUnit(itemDTO.getOverchargedQtyBasicUnit());
            dtl.setOverchargedQtyUnitSales(itemDTO.getOverchargedQtyUnitSales());
            dtl.setUnderchargedQtyBasicUnit(itemDTO.getUnderchargedQtyBasicUnit());
            dtl.setUnderchargedQtyUnitSales(itemDTO.getUnderchargedQtyUnitSales());
            dtl.setRemarks(itemDTO.getRemarks() == null ? "" : itemDTO.getRemarks());
            iOverseaDeliveryNoteDtlService.update(dtl, queryWrapper);
        }
    }

    /**
     海外收货任务提交SAP。
     修改后SPMS交货单状态设计：
         默认0待到货/SPMS可从SAP更新单据；√ 状态停留
         1-收货中/SAP凭证撤销；√ 状态停留
         2-入库完成；√ 状态停留
         6-收货多收提交SAP失败；√ 状态停留
         7-收货多收提交SAP成功；—— 中间状态
         8-收货少收提交SAP失败；√ 状态停留
         9-收货少收提交SAP成功；—— 中间状态
         10-提交SAP完成；—— 中间状态
         11-收货完成；√ 状态停留
         12-关闭/废单;√ 状态停留
     单据状态变化：
        2-6; 2-7; 2-8; 2-9; 2-10; 2-11;
        6-6; 6-7; 6-8; 6-9; 6-10; 6-11;
        8-8; 8-9; 8-10; 8-11;
     盘盈提交SAP 701-盘盈，702-盘亏；———— 接口不适用此场景 20211123；
     多收对应移动类型Z16，少收对应移动类型Z15；———— 海外收货多收另起接口；收货少收提交SAP走成本中心入库，20211123；
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult overseaDeliveryNoteToSap(String sapDeliveryNote, String underPostingDate,
                                                                Integer dataVersion, String costCenter, String userId) {
        try {
            ResponseResult checkToSap = checkDnToSap(sapDeliveryNote, underPostingDate, dataVersion, costCenter);
            if (checkToSap.getCode() != SUCCESS){
                return checkToSap;
            }
            QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
            OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);

            String spmsStatus = overseaDeliveryNote.getSpmsStatus();
            if (OVERSEA_WHS_IN_DONE.getCode().equals(spmsStatus) || OVERCHARGED_TO_SAP_ERROR.getCode().equals(spmsStatus)){
                //List<Map<String, Object>> overchargedDataItem = iOverseaDeliveryNoteDtlService.getOverchargedItemsToSap(sapDeliveryNote);
                //List<Map<String, Object>> underchargedDataItem = iOverseaDeliveryNoteDtlService.getUnderchargedItemsToSap(sapDeliveryNote);
                List<Map<String, Object>> overchargedDataItem = new ArrayList<>();
                List<Map<String, Object>> underchargedDataItem = iOverseaDeliveryNoteDtlService.getUnderchargedItemsToSapAnomalyPost(sapDeliveryNote, costCenter);
                if ((overchargedDataItem != null && overchargedDataItem.size() > 0) || (underchargedDataItem != null && underchargedDataItem.size() > 0)){
                    if (overchargedDataItem != null && overchargedDataItem.size() > 0){
                        Map<String, Object> dataHead = this.baseMapper.dataHead(sapDeliveryNote, "701", underPostingDate);
                        JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, overchargedDataItem, "Z_SPMS_SKU_CHECK", "SKU_CHECK");
                        log.info("=======海外收货交货单多收盘盈请求SAP dataToSap=========\n" + dataToSap);
                        JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                        log.info("=======海外收货交货单多收盘盈请求SAP响应结果 message=========\n" + message);
                        JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                        if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
                            String sapVoucherNumber = RETURN_DATA.getString("O_MBLNR").trim();
                            String sapVoucherYear = RETURN_DATA.getString("O_MJAHR").trim();
                            overseaDeliveryNote.setCostCenter(costCenter);
                            overseaDeliveryNote.setSpmsStatus(OVERCHARGED_TO_SAP.getCode());
                            overseaDeliveryNote.setPostingDate(underPostingDate);
                            overseaDeliveryNote.setSapVoucherNumber(sapVoucherNumber);
                            overseaDeliveryNote.setSapVoucherYear(sapVoucherYear);
                            this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                            iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERCHARGED_TO_SAP.getDescZh() + ":" + sapVoucherNumber,
                                    OVERCHARGED_TO_SAP.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单多收提交SAP");
                        } else {
                            overseaDeliveryNote.setCostCenter(costCenter);
                            overseaDeliveryNote.setSpmsStatus(OVERCHARGED_TO_SAP_ERROR.getCode());
                            this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                            iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERCHARGED_TO_SAP_ERROR.getDescZh(),
                                    OVERCHARGED_TO_SAP_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单多收提交SAP");

                            return ResponseResult.error("收货多收提交SAP错误")
                                    .add("sapReturnedMessage", message)
                                    .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                                    .add("dataToSap", dataToSap);
                        }
                    }
                    if (underchargedDataItem != null && underchargedDataItem.size() > 0){
                        //Map<String, Object> dataHead = this.baseMapper.dataHead(sapDeliveryNote, "702", postingDate);
                        //JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, underchargedDataItem, "Z_SPMS_SKU_CHECK", "SKU_CHECK");
                        Map<String, Object> dataHead = this.baseMapper.dataHeadAnomalyPost(sapDeliveryNote, "Z15", underPostingDate);
                        JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, underchargedDataItem, "Z_SPMS_ANOMALY_POST", "ANOMALY_POST");
                        log.info("=======海外收货交货单少收成本中心入库请求SAP dataToSap=========\n" + dataToSap);
                        JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                        log.info("=======海外收货交货单少收成本中心入库请求SAP响应结果 message=========\n" + message);
                        JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                        if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
                            String underVoucherNumber = RETURN_DATA.getString("O_MBLNR").trim();
                            String underVoucherYear = RETURN_DATA.getString("O_MJAHR").trim();
                            overseaDeliveryNote.setSpmsStatus(UNDERCHARGED_TO_SAP.getCode());
                            overseaDeliveryNote.setCostCenter(costCenter);
                            overseaDeliveryNote.setUnderPostingDate(underPostingDate);
                            overseaDeliveryNote.setUnderVoucherNumber(underVoucherNumber);
                            overseaDeliveryNote.setUnderVoucherYear(underVoucherYear);
                            this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                            iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, UNDERCHARGED_TO_SAP.getDescZh() + ":" + underVoucherNumber,
                                    UNDERCHARGED_TO_SAP.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单少收提交SAP");
                        } else {
                            overseaDeliveryNote.setCostCenter(costCenter);
                            overseaDeliveryNote.setSpmsStatus(UNDERCHARGED_TO_SAP_ERROR.getCode());
                            this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                            iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, UNDERCHARGED_TO_SAP_ERROR.getDescZh(),
                                    UNDERCHARGED_TO_SAP_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单少收提交SAP");

                            return ResponseResult.error("收货少收提交SAP错误")
                                    .add("sapReturnedMessage", message)
                                    .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                                    .add("dataToSap", dataToSap);
                        }
                    }
                    overseaDeliveryNote.setCostCenter(costCenter);
                    overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_SUBMIT_SAP.getCode());
                    this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_SUBMIT_SAP.getDescZh(), OVERSEA_DN_SUBMIT_SAP.getDescEn(), "");
                }
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_COMPLETED.getCode());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_COMPLETED.getDescZh(), OVERSEA_DN_COMPLETED.getDescEn(), "");
            }

            if (UNDERCHARGED_TO_SAP_ERROR.getCode().equals(spmsStatus)){
                //Map<String, Object> dataHead = this.baseMapper.dataHead(sapDeliveryNote, "702", postingDate);
                //List<Map<String, Object>> underchargedDataItem = iOverseaDeliveryNoteDtlService.getUnderchargedItemsToSap(sapDeliveryNote);
                Map<String, Object> dataHead = this.baseMapper.dataHeadAnomalyPost(sapDeliveryNote, "Z15", underPostingDate);
                List<Map<String, Object>> underchargedDataItem = iOverseaDeliveryNoteDtlService.getUnderchargedItemsToSapAnomalyPost(sapDeliveryNote, costCenter);
                if (underchargedDataItem != null && underchargedDataItem.size() > 0){
                    JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, underchargedDataItem, "Z_SPMS_ANOMALY_POST", "ANOMALY_POST");
                    log.info("=======海外收货交货单少收成本中心入库请求SAP dataToSap=========\n" + dataToSap);
                    JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                    log.info("=======海外收货交货单少收成本中心入库请求SAP响应结果 message=========\n" + message);
                    JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");

                    if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
                        String underVoucherNumber = RETURN_DATA.getString("O_MBLNR").trim();
                        String underVoucherYear = RETURN_DATA.getString("O_MJAHR").trim();
                        overseaDeliveryNote.setCostCenter(costCenter);
                        overseaDeliveryNote.setSpmsStatus(UNDERCHARGED_TO_SAP.getCode());
                        overseaDeliveryNote.setUnderPostingDate(underPostingDate);
                        overseaDeliveryNote.setUnderVoucherNumber(underVoucherNumber);
                        overseaDeliveryNote.setUnderVoucherYear(underVoucherYear);
                        this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                        iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, UNDERCHARGED_TO_SAP.getDescZh() + ":" + underVoucherNumber,
                                UNDERCHARGED_TO_SAP.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单少收提交SAP");
                    } else {
                        overseaDeliveryNote.setCostCenter(costCenter);
                        overseaDeliveryNote.setSpmsStatus(UNDERCHARGED_TO_SAP_ERROR.getCode());
                        this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                        iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, UNDERCHARGED_TO_SAP_ERROR.getDescZh(),
                                UNDERCHARGED_TO_SAP_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单少收提交SAP");

                        return ResponseResult.error("收货少收提交SAP错误")
                                .add("sapReturnedMessage", message)
                                .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                                .add("dataToSap", dataToSap);
                    }
                    overseaDeliveryNote.setCostCenter(costCenter);
                    overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_SUBMIT_SAP.getCode());
                    this.baseMapper.update(overseaDeliveryNote, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_SUBMIT_SAP.getDescZh(), OVERSEA_DN_SUBMIT_SAP.getDescEn(), "");

                    overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_COMPLETED.getCode());
                    this.baseMapper.update(overseaDeliveryNote, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_COMPLETED.getDescZh(), OVERSEA_DN_COMPLETED.getDescEn(), "");
                } else {
                    return ResponseResult.error("收货少收无可提交SAP少收项");
                }
            }
            return ResponseResult.success("收货完成").add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote));
        }catch (FeignException feignException){
            feignException.printStackTrace();
            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("收货完成更新单据或提交SAP失败 Exception").add("error", e.getMessage());
        }
    }

    ResponseResult checkDnToSap(String sapDeliveryNote, String underPostingDate, Integer dataVersion, String costCenter){
        if (sapDeliveryNote == null || underPostingDate == null || costCenter == null){
            return ResponseResult.error("请求参数不能为空");
        }
        QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);
        if (!dataVersion.equals(overseaDeliveryNote.getDataVersion())){
            return ResponseResult.error("交货单信息已更新请刷新后重试");
        }
        String spmsStatus = overseaDeliveryNote.getSpmsStatus();
        if (!OVERSEA_WHS_IN_DONE.getCode().equals(spmsStatus) &&
                !OVERCHARGED_TO_SAP_ERROR.getCode().equals(spmsStatus) &&
                !UNDERCHARGED_TO_SAP_ERROR.getCode().equals(spmsStatus)){
            return ResponseResult.error("当前状态禁止此操作");
        }
        return ResponseResult.success();
    }

    /**
     1收货中/SAP凭证撤销
        撤销 —— 前提是无有效入库任务 1-0；检查无有效入库任务才能退回到待到货；更新状态、删除实收工厂、实收仓库、实际到货日期、数据状态 等字段；
     2入库完成
         不存在少收
            撤销 —— 更新交货单状态 2-1；
         存在少收
            撤销 —— 撤回少收的 入库凭证(Z_SPMS_CANCEL)，成功则记录 入库撤销 凭证等信息 2-1；失败记日志 2-2；
     8收货少收提交SAP失败
        存在少收
            撤销 —— 撤回少收的 入库凭证(Z_SPMS_CANCEL)，成功则记录 入库撤销 凭证等信息 8-1；失败记日志 8-8；
     11收货完成
         不存在少收
            撤销 —— 11-1；
         存在少收
            撤销 —— 撤回少收的 少收凭证(Z_SPMS_CANCEL)，成功则记录 少收撤销 凭证等信息 11-2；失败记日志 11-11；
     * @param sapDeliveryNote
     * @param cancelUnderPostingDate
     * @param dataVersion
     * @param userId
     * @return
     */
    @Override
    public synchronized ResponseResult cancelOverseaDeliveryNote(String sapDeliveryNote, String cancelPostingDate,
                                                                 String cancelUnderPostingDate, Integer dataVersion, String userId) {
        ResponseResult checkCancelResult = checkCancel(sapDeliveryNote, cancelPostingDate, cancelUnderPostingDate, dataVersion);
        if (checkCancelResult.getCode() != SUCCESS){
            return checkCancelResult;
        }
        QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);
        String spmsStatus = overseaDeliveryNote.getSpmsStatus();
        if (OVERSEA_DN_RECEIVING.getCode().equals(spmsStatus)){
            overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_WAITING.getCode());
            overseaDeliveryNote.setArrivalDate("");
            overseaDeliveryNote.setActualWerksReceive("");
            overseaDeliveryNote.setActualWhsLocationCodeReceive("");
            this.baseMapper.update(overseaDeliveryNote, queryWrapper);

            /** 交货单撤回到待到货，更新交货单关联的 交货单明细、装箱单、装箱单明细、装箱单箱码关系 数据解除锁定可被SAP更新 */
            unlockDataUpdateBySap(overseaDeliveryNote);

            iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_CANCEL_TO_WAITING.getDescZh(), OVERSEA_DN_CANCEL_TO_WAITING.getDescEn(), "");
        }
        if (OVERSEA_WHS_IN_DONE.getCode().equals(spmsStatus)){
            String sapVoucherNumber = overseaDeliveryNote.getSapVoucherNumber();
            String sapVoucherYear = overseaDeliveryNote.getSapVoucherYear();
            if (StringUtils.isEmpty(sapVoucherNumber)){
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_RECEIVING.getCode());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_CANCEL_TO_RECEIVING.getDescZh(), OVERSEA_DN_CANCEL_TO_RECEIVING.getDescEn(), "");
            } else {
                JSONObject dataToSap = cancelWhsInToSap(sapVoucherNumber, sapVoucherYear, cancelPostingDate);
                log.info("=======海外收货交货单少收 入库凭证 撤销请求SAP dataToSap=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======海外收货交货单少收 入库凭证 撤销请求SAP响应结果 message=========\n" + message);
                JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))) {
                    String cancelVoucherNumber = RETURN_DATA.getString("0_MBLNR");
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_WHS_IN_CANCEL.getDescZh() + ":" + cancelVoucherNumber,
                            OVERSEA_DN_WHS_IN_CANCEL.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "入库凭证撤销提交SAP成功");
                    overseaDeliveryNote.setCancelVoucherNumber(cancelVoucherNumber);
                    overseaDeliveryNote.setCancelPostingDate(cancelPostingDate);
                    overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_RECEIVING.getCode());
                    this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote,
                            OVERSEA_DN_CANCEL_TO_RECEIVING.getDescZh(), OVERSEA_DN_CANCEL_TO_RECEIVING.getDescEn(), "");

                } else {
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_WHS_IN_CANCEL_ERROR.getDescZh(),
                            OVERSEA_DN_WHS_IN_CANCEL_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "入库凭证撤销提交SAP失败");
                    return ResponseResult.error("入库凭证撤销提交SAP失败")
                            .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                            .add("sapReturnedMessage", message)
                            .add("dataToSap", dataToSap);
                }
            }

        }
        if (UNDERCHARGED_TO_SAP_ERROR.getCode().equals(spmsStatus)){
            String sapVoucherNumber = overseaDeliveryNote.getSapVoucherNumber();
            String sapVoucherYear = overseaDeliveryNote.getSapVoucherYear();
            JSONObject dataToSap = cancelWhsInToSap(sapVoucherNumber, sapVoucherYear, cancelPostingDate);
            log.info("=======海外收货交货单少收 入库凭证 撤销请求SAP dataToSap=========\n" + dataToSap);
            JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
            log.info("=======海外收货交货单少收 入库凭证 撤销请求SAP响应结果 message=========\n" + message);
            JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))) {
                String cancelVoucherNumber = RETURN_DATA.getString("0_MBLNR");
                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_WHS_IN_CANCEL.getDescZh() + ":" + cancelVoucherNumber,
                        OVERSEA_DN_WHS_IN_CANCEL.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "入库凭证撤销提交SAP成功");
                overseaDeliveryNote.setCancelVoucherNumber(cancelVoucherNumber);
                overseaDeliveryNote.setCancelPostingDate(cancelPostingDate);
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_RECEIVING.getCode());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote,
                        OVERSEA_DN_CANCEL_TO_RECEIVING.getDescZh(), OVERSEA_DN_CANCEL_TO_RECEIVING.getDescEn(), "");
            } else {
                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_WHS_IN_CANCEL_ERROR.getDescZh(),
                        OVERSEA_DN_WHS_IN_CANCEL_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "入库凭证撤销提交SAP失败");
                return ResponseResult.error("入库凭证撤销提交SAP失败")
                        .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                        .add("sapReturnedMessage", message)
                        .add("dataToSap", dataToSap);
            }
        }
        if (OVERSEA_DN_COMPLETED.getCode().equals(spmsStatus)){
            String underVoucherNumber = overseaDeliveryNote.getUnderVoucherNumber();
            if (StringUtils.isEmpty(underVoucherNumber)){
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_RECEIVING.getCode());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_CANCEL_TO_RECEIVING.getDescZh(), OVERSEA_DN_CANCEL_TO_RECEIVING.getDescEn(), "");
            } else {
                Map<String, Object> dataHead = this.baseMapper.dataHeadCancelAnomalyPost(sapDeliveryNote, cancelUnderPostingDate);
                JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, null, "Z_SPMS_CANCEL", "SPMS_CANCEL");
                log.info("=======海外收货交货单少收成本中心入库撤销请求SAP dataToSap=========\n" + dataToSap);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                log.info("=======海外收货交货单少收成本中心入库撤销请求SAP响应结果 message=========\n" + message);
                JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
                    String cancelUnderVoucherNumber = RETURN_DATA.getString("0_MBLNR");
                    overseaDeliveryNote.setCancelUnderPostingDate(cancelUnderPostingDate);
                    overseaDeliveryNote.setCancelUnderVoucherNumber(cancelUnderVoucherNumber);
                    overseaDeliveryNote.setSpmsStatus(OVERSEA_WHS_IN_DONE.getCode());
                    this.baseMapper.update(overseaDeliveryNote, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_CANCEL_TO_DONE.getDescZh() + ":" + cancelUnderVoucherNumber,
                            OVERSEA_DN_CANCEL_TO_DONE.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单少收撤销提交SAP");

                }else {
                    iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_CANCEL_ERROR.getDescZh(),
                            OVERSEA_DN_CANCEL_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "交货单少收撤销提交SAP");
                    return ResponseResult.error("撤销失败")
                            .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                            .add("sapReturnedMessage", message)
                            .add("dataToSap", dataToSap);
                }
            }
        }
        return ResponseResult.success("撤销成功").add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote));
    }

    ResponseResult checkCancel(String sapDeliveryNote, String cancelPostingDate, String cancelUnderPostingDate, Integer dataVersion){
        if (StringUtils.isEmpty(sapDeliveryNote)){
            return ResponseResult.error("请求参数错误");
        }
        QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);
        if (overseaDeliveryNote == null){
            return ResponseResult.error("交货单信息查询不存在");
        }
        if (!dataVersion.equals(overseaDeliveryNote.getDataVersion())){
            return ResponseResult.error("交货单信息已更新请刷新后重试");
        }
        String spmsStatus = overseaDeliveryNote.getSpmsStatus();
        if (OVERSEA_DN_RECEIVING.getCode().equals(spmsStatus)){
            List<OverseaWhsIn> overseaWhsInList = this.baseMapper.getValidateTask(sapDeliveryNote);
            if (overseaWhsInList != null && overseaWhsInList.size() > 0){
                return ResponseResult.error("1-0 交货单存在关联有效入库任务，请先关闭入库任务");
            }
        } else if (OVERSEA_WHS_IN_DONE.getCode().equals(spmsStatus)){
            String sapVoucherNumber = overseaDeliveryNote.getSapVoucherNumber();
            if (StringUtils.isNotEmpty(sapVoucherNumber)){
                if (StringUtils.isEmpty(cancelPostingDate)){
                    return ResponseResult.error("撤销入库凭证过账日期不允许为空");
                }
            }
        } else if (UNDERCHARGED_TO_SAP_ERROR.getCode().equals(spmsStatus)){
            if (StringUtils.isEmpty(cancelPostingDate)){
                return ResponseResult.error("撤销入库凭证过账日期不允许为空");
            }
        } else if (OVERSEA_DN_COMPLETED.getCode().equals(spmsStatus)){
            /*** 11-1; 如果少收凭证字段有值则先撤回少收凭证，有少收凭证时才需要填写撤销过账日期字段，没有的直接更新交货单状态；*/
            String underVoucherNumber = overseaDeliveryNote.getUnderVoucherNumber();
            if (StringUtils.isNotEmpty(underVoucherNumber)){
                if (StringUtils.isEmpty(cancelUnderPostingDate)){
                    return ResponseResult.error("撤销少收凭证过账日期不允许为空");
                }
            }
        } else {
            return ResponseResult.error("当前状态禁止此操作");
        }
        return ResponseResult.success();
    }

    JSONObject cancelWhsInToSap(String sapVoucherNumber, String sapVoucherYear, String cancelPostingDate){
        JSONObject doc = new JSONObject();

        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        JSONObject Head = new JSONObject();

        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());
        Head.put("iMblnr", sapVoucherNumber);
        Head.put("iMjahr", sapVoucherYear);
        Head.put("iBudat", cancelPostingDate.replaceAll("-", ""));
        REQUEST_DATA.put("Head", Head);
        REQUEST_DATA.put("Operation", "Z_SPMS_CANCEL");
        REQUEST_DATA.put("Type", "SPMS_CANCEL");
        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        doc.put("REQUEST", REQUEST);
        return doc;
    }

    /** 交货单撤回到待到货，更新交货单关联的 交货单明细、装箱单、装箱单明细、装箱单箱码关系 数据解除锁定可被SAP更新 */
    void unlockDataUpdateBySap(OverseaDeliveryNote overseaDeliveryNote){
        String sapDeliveryNote = overseaDeliveryNote.getSapDeliveryNote();
        String sapPackageList = overseaDeliveryNote.getSapPackageList();

        QueryWrapper<OverseaDeliveryNoteDtl> deliveryNoteDtlQueryWrapper = new QueryWrapper<OverseaDeliveryNoteDtl>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        QueryWrapper<OverseaPackageList> packageListQueryWrapper = new QueryWrapper<OverseaPackageList>().eq("SAP_PACKAGE_LIST", sapPackageList);
        QueryWrapper<OverseaPackageListDtl> packageListDtlQueryWrapper = new QueryWrapper<OverseaPackageListDtl>().eq("SAP_PACKAGE_LIST", sapPackageList);
        QueryWrapper<OverseaPackageListBox> packageListBoxQueryWrapper = new QueryWrapper<OverseaPackageListBox>().eq("SAP_PACKAGE_LIST", sapPackageList);

        OverseaDeliveryNoteDtl overseaDeliveryNoteDtl = new OverseaDeliveryNoteDtl();
        overseaDeliveryNoteDtl.setDataStatus(DATA_STATUS_0);
        iOverseaDeliveryNoteDtlService.update(overseaDeliveryNoteDtl, deliveryNoteDtlQueryWrapper);

        OverseaPackageList overseaPackageList = new OverseaPackageList();
        overseaPackageList.setDataStatus(DATA_STATUS_0);
        iOverseaPackageListService.update(overseaPackageList, packageListQueryWrapper);

        OverseaPackageListDtl overseaPackageListDtl = new OverseaPackageListDtl();
        overseaPackageListDtl.setDataStatus(DATA_STATUS_0);
        iOverseaPackageListDtlService.update(overseaPackageListDtl, packageListDtlQueryWrapper);

        OverseaPackageListBox overseaPackageListBox = new OverseaPackageListBox();
        overseaPackageListBox.setDataStatus(DATA_STATUS_0);
        iOverseaPackageListBoxService.update(overseaPackageListBox, packageListBoxQueryWrapper);
    }



    /**
     检查海外收货交货单关联信息是否能被拆分入库任务
     1.交货单存在必须有明细行；
     2.交货单所属装箱单信息存在；
     3.交货单关联装箱单明细必须存在；
     4.交货单所有明细行必须能对上装箱单明细行数据；通过 公司间采购订单号 和 公司间采购订单行号；
     5.交货单关联出的装箱单明细行，都必须能对上箱码明细行数据；通过 装箱单号 和 装箱单行号；
     以上五点都满足则认定为可用数据。
     */
    @Override
    public ResponseResult checkOverseaDeliveryNote(String sapDeliveryNote) {
        OverseaDeliveryNote overseaDeliveryNote = getOverseaDn(sapDeliveryNote);
        if (overseaDeliveryNote == null){
            return ResponseResult.error("交货单信息查询不存在");
        }
        String sapPackageList = overseaDeliveryNote.getSapPackageList();
        if (StringUtils.isEmpty(sapPackageList)){
            return ResponseResult.error("交货单关联装箱单信息缺失");
        }

        QueryWrapper<OverseaPackageList> queryWrapperPL = new QueryWrapper<OverseaPackageList>().eq("SAP_PACKAGE_LIST", sapPackageList);
        OverseaPackageList overseaPackageList = iOverseaPackageListService.getOne(queryWrapperPL);
        if (overseaPackageList == null){
            return ResponseResult.error("交货单关联装箱单信息不存在");
        }

        QueryWrapper<OverseaDeliveryNoteDtl> queryWrapperDNL = new QueryWrapper<OverseaDeliveryNoteDtl>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        List<OverseaDeliveryNoteDtl> overseaDeliveryNoteDtlList = iOverseaDeliveryNoteDtlService.list(queryWrapperDNL);
        if (overseaDeliveryNoteDtlList == null || overseaDeliveryNoteDtlList.size() == 0){
            return ResponseResult.error("交货单明细行不存在");
        }

        for (OverseaDeliveryNoteDtl dtl : overseaDeliveryNoteDtlList){
            String sapDeliveryNoteItem = dtl.getSapDeliveryNoteItem();
            String purchaseNo = dtl.getPurchaseNo();
            String purchaseNoItem = dtl.getPurchaseNoItem();
            if (StringUtils.isEmpty(purchaseNo) || StringUtils.isEmpty(purchaseNoItem)){
                return ResponseResult.error("交货单:" + sapDeliveryNote + "行号:" + sapDeliveryNoteItem
                        + "，关联公司间采购订单号:" + purchaseNo + "或公司间采购订单行号:" + purchaseNoItem + "数据为空");
            }

            QueryWrapper<OverseaPackageListDtl> queryWrapperPLD = new QueryWrapper<OverseaPackageListDtl>()
                    .eq("PURCHASE_NO", purchaseNo).eq("PURCHASE_NO_ITEM", purchaseNoItem);
            List<OverseaPackageListDtl> overseaPackageListDtlList = iOverseaPackageListDtlService.list(queryWrapperPLD);
            if (overseaPackageListDtlList == null || overseaPackageListDtlList.size() == 0){
                return ResponseResult.error("交货单:" + sapDeliveryNote + "行号:" + sapDeliveryNoteItem + "，关联装箱单明细行数据为空");
            }

            for (OverseaPackageListDtl oplDtl : overseaPackageListDtlList){
                String packageList = oplDtl.getSapPackageList();
                String packageListItem = oplDtl.getSapPackageListItem();
                if (StringUtils.isEmpty(packageList) || StringUtils.isEmpty(packageListItem)){
                    return ResponseResult.error("交货单:" + sapDeliveryNote + "行号:" + sapDeliveryNoteItem
                            + "，关联装箱单号:" + packageList + "或装箱单行号:" + packageListItem + "数据为空");
                }

                QueryWrapper<OverseaPackageListBox> queryWrapperPLB = new QueryWrapper<OverseaPackageListBox>()
                        .eq("SAP_PACKAGE_LIST", packageList).eq("SAP_PACKAGE_LIST_ITEM", packageListItem);
                List<OverseaPackageListBox> overseaPackageListBoxList = iOverseaPackageListBoxService.list(queryWrapperPLB);
                if (overseaPackageListBoxList == null || overseaPackageListBoxList.size() == 0){
                    return ResponseResult.error("交货单:" + sapDeliveryNote + "行号:" + sapDeliveryNoteItem
                            + "，关联装箱单号:" + packageList + "装箱单行号:" + packageListItem + "，关联箱码明细行数据信息不存在");
                }
            }

        }
        return ResponseResult.success("交货单数据正常");
    }

    /** 交货单损益提交OA审批
     * SPMS单据状态(默认0待到货;1收货中/SAP撤销;2提交OA成功/收货完成;3提交OA失败;4OA审批不通过;5OA审批通过/提交SAP失败;6提交SAP成功;7关闭;)
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult overseaDeliveryNoteToOa(OverseaDeliveryNoteOaDTO overseaDeliveryNoteOaDTO, SpmsUser spmsUser) {
        try {
            ResponseResult checkDataToOa = checkDnToOa(overseaDeliveryNoteOaDTO);
            if (checkDataToOa.getCode() != SUCCESS){
                return checkDataToOa;
            }
            String sapDeliveryNote = overseaDeliveryNoteOaDTO.getSapDeliveryNote();
            QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
            int dnDataToOaResult = dnDataToOa(overseaDeliveryNoteOaDTO, spmsUser);
            if (dnDataToOaResult > 0){
                OverseaDeliveryNote overseaDeliveryNote = new OverseaDeliveryNote();
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_SUBMIT_OA.getCode());
                overseaDeliveryNote.setOaWorkflow("3168");
                overseaDeliveryNote.setOaBianhao(String.valueOf(dnDataToOaResult));
                overseaDeliveryNote.setSubmitOaDate(overseaDeliveryNoteOaDTO.getSubmitOaDate());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                List<OverseaDeliveryNoteSapItemDTO> dnItems = overseaDeliveryNoteOaDTO.getOverseaDeliveryNoteItem();
                for (OverseaDeliveryNoteSapItemDTO dto : dnItems){
                    String sapDeliveryNoteItem = dto.getSapDeliveryNoteItem();
                    QueryWrapper<OverseaDeliveryNoteDtl> dtlQueryWrapper = new QueryWrapper<OverseaDeliveryNoteDtl>()
                            .eq("SAP_DELIVERY_NOTE", sapDeliveryNote).eq("SAP_DELIVERY_NOTE_ITEM", sapDeliveryNoteItem);
                    OverseaDeliveryNoteDtl overseaDeliveryNoteDtl = new OverseaDeliveryNoteDtl();
                    overseaDeliveryNoteDtl.setActualQtyBasicUnit(dto.getActualQtyBasicUnit() == null ? 0.0 : dto.getActualQtyBasicUnit());
                    overseaDeliveryNoteDtl.setActualQtyUnitSales(dto.getActualQtyUnitSales() == null ? 0.0 : dto.getActualQtyUnitSales());
                    overseaDeliveryNoteDtl.setOverchargedQtyBasicUnit(dto.getOverchargedQtyBasicUnit() == null ? 0.0 : dto.getOverchargedQtyBasicUnit());
                    overseaDeliveryNoteDtl.setOverchargedQtyUnitSales(dto.getOverchargedQtyUnitSales() == null ? 0.0 : dto.getOverchargedQtyUnitSales());
                    overseaDeliveryNoteDtl.setUnderchargedQtyBasicUnit(dto.getUnderchargedQtyBasicUnit() == null ? 0.0 : dto.getUnderchargedQtyBasicUnit());
                    overseaDeliveryNoteDtl.setUnderchargedQtyUnitSales(dto.getUnderchargedQtyUnitSales() == null ? 0.0 : dto.getUnderchargedQtyUnitSales());
                    overseaDeliveryNoteDtl.setRemarks(dto.getRemarks() == null ? "" : dto.getRemarks());
                    iOverseaDeliveryNoteDtlService.update(overseaDeliveryNoteDtl, dtlQueryWrapper);
                }

                iOverseaOperateLogService.addOverseaOperateLog(spmsUser.getUserId(), sapDeliveryNote, OVERSEA_DN_UPDATE.getDescZh(),
                        OVERSEA_DN_UPDATE.getDescEn(), spmsLog, overseaDeliveryNoteOaDTO.toString(), "", "");

                return ResponseResult.success("交货单损益信息提交OA审批成功")
                        .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                        .add("overseaDeliveryNoteItem", getOverseaDeliveryNoteItem(sapDeliveryNote))
                        .add("oaBianhao", dnDataToOaResult);
            } else if (dnDataToOaResult == -2) {
                OverseaDeliveryNote overseaDeliveryNote = new OverseaDeliveryNote();
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_SUBMIT_OA_ERROR.getCode());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                return ResponseResult.error("-2 用户没有流程创建权限，交货单损益信息提交OA审批失败")
                        .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                        .add("overseaDeliveryNoteItem", getOverseaDeliveryNoteItem(sapDeliveryNote))
                        .add("oaErrorCode", dnDataToOaResult);
            } else {
                OverseaDeliveryNote overseaDeliveryNote = new OverseaDeliveryNote();
                overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_SUBMIT_OA_ERROR.getCode());
                this.baseMapper.update(overseaDeliveryNote, queryWrapper);

                return ResponseResult.error("交货单损益信息提交OA审批失败")
                        .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote))
                        .add("overseaDeliveryNoteItem", getOverseaDeliveryNoteItem(sapDeliveryNote))
                        .add("oaErrorCode", dnDataToOaResult);
            }
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("提交OA失败 Exception").add("error", e.getMessage());
        }
    }

    ResponseResult checkDnToOa(OverseaDeliveryNoteOaDTO overseaDeliveryNoteOaDTO){
        if (overseaDeliveryNoteOaDTO == null || overseaDeliveryNoteOaDTO.getOverseaDeliveryNoteItem() == null){
            return ResponseResult.error("请求参数不能为空");
        }
        String sapDeliveryNote = overseaDeliveryNoteOaDTO.getSapDeliveryNote();
        String submitOaDate = overseaDeliveryNoteOaDTO.getSubmitOaDate();
        if (StringUtils.isEmpty(sapDeliveryNote) || StringUtils.isEmpty(submitOaDate)
                || overseaDeliveryNoteOaDTO.getDataVersion() == null){
            return ResponseResult.error("请求参数交货单号提交OA日期不能为空");
        }
        if (INVALID_DATE.equals(submitOaDate)){
            return ResponseResult.error("提交OA日期格式错误请重试");
        }
        QueryWrapper<OverseaDeliveryNote> queryWrapper = new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
        OverseaDeliveryNote overseaDeliveryNote = this.baseMapper.selectOne(queryWrapper);
        if (overseaDeliveryNote == null){
            return ResponseResult.error("请求交货单不存在");
        }
        int dataVersion = overseaDeliveryNote.getDataVersion();
        if (dataVersion != overseaDeliveryNoteOaDTO.getDataVersion()){
            return ResponseResult.error("交货单信息已更新请刷新后重试");
        }
        String spmsStatus = overseaDeliveryNote.getSpmsStatus();
        if (!OVERSEA_DN_WAITING.getCode().equals(spmsStatus)
                && !OVERSEA_DN_RECEIVING.getCode().equals(spmsStatus)
                && !OVERSEA_DN_SUBMIT_OA_ERROR.getCode().equals(spmsStatus)
                && !OVERSEA_DN_OA_REJECT.getCode().equals(spmsStatus)){
            return ResponseResult.error("交货单当前状态禁止此操作");
        }
        List<OverseaWhsIn> overseaWhsInList = this.baseMapper.getDoingTask(sapDeliveryNote);
        if (overseaWhsInList != null && overseaWhsInList.size() > 0){
            return ResponseResult.error("交货单还有进行中的入库任务，请先完成入库任务");
        }
        return ResponseResult.success();
    }

    /**
     * 新流程的requestid
     * 如果小于等于0表示失败
     * -1：创建流程失败
     * -2：用户没有流程创建权限
     * -3：创建流程基本信息失败
     * -4：保存表单主表信息失败
     * -5：更新紧急程度失败
     * -6：流程操作者失败
     * -7：流转至下一节点失败
     * -8：节点附加操作失败
     * @param overseaDeliveryNoteOaDTO
     * @param spmsUser
     * @return
     */
    int dnDataToOa(OverseaDeliveryNoteOaDTO overseaDeliveryNoteOaDTO, SpmsUser spmsUser){
        String sapDeliveryNote = overseaDeliveryNoteOaDTO.getSapDeliveryNote();
        List<OverseaDeliveryNoteSapItemDTO> itemDTOList = overseaDeliveryNoteOaDTO.getOverseaDeliveryNoteItem();

        ExtHrmresourcesPortTypeProxy proxy = new ExtHrmresourcesPortTypeProxy();
        RequestServicePortTypeProxy wfproxy = new RequestServicePortTypeProxy();
        try {
            RequestInfo reqinfo = new RequestInfo();
            reqinfo.setCreatorid(spmsUser.getWorkId()); // OAID 提交人
            reqinfo.setWorkflowid(workflow3168);// workflowid 为测试系统ID
            reqinfo.setRequestlevel("0");// 紧急程度 默认
            reqinfo.setRemindtype("0"); // 默认
            reqinfo.setIsNextFlow("1"); // 默认
            reqinfo.setDescription("海外收货交货单号" + sapDeliveryNote + "损益结果审批"); // 自定义

            Map<String, Object> mapHead = new HashMap<>();
            mapHead.put("bianhao", "");
            mapHead.put("workcode", spmsUser.getUserId());
            mapHead.put("workflowdate", overseaDeliveryNoteOaDTO.getSubmitOaDate());
            mapHead.put("requestuserid", spmsUser.getWorkId());
            mapHead.put("dep", spmsUser.getDeptId() == null  ? "" : spmsUser.getDeptId());
            mapHead.put("jobtitle", spmsUser.getPositionId() == null  ? "" : spmsUser.getPositionId());
            mapHead.put("sub", spmsUser.getCompany() == null ? "" : spmsUser.getCompany());
            mapHead.put("fendian", spmsUser.getBranchPoint() == null ? "" : spmsUser.getBranchPoint());
            mapHead.put("joblevel", "");
            mapHead.put("area", "");
            mapHead.put("tzremark", "调账说明");
            mapHead.put("additional", "1");
            mapHead.put("Executivepersonnel", spmsUser.getWorkId());
            mapHead.put("posdh", sapDeliveryNote);
            mapHead.put("spmsordernum", sapDeliveryNote);
            mapHead.put("businessType", BUSINESS_TYPE_OVERSEA_DELIVERY);

            MainTableInfo wmi = new MainTableInfo();
            Property[] wrti = new Property[mapHead.size()];
            int i = 0;
            for (Map.Entry<String, Object> entry : mapHead.entrySet()){
                wrti[i] = new Property();
                wrti[i].setName(entry.getKey());
                wrti[i].setValue(entry.getValue().toString());
                i ++;
            }
            wmi.setProperty(wrti);

            List<Map<String, Object>> mapList = new ArrayList<>();
            for (int j = 0; j < itemDTOList.size(); j ++){
                OverseaDeliveryNoteSapItemDTO itemDTO = itemDTOList.get(j);
                String sapDn = itemDTO.getSapDeliveryNote();
                String sapDnItem = itemDTO.getSapDeliveryNoteItem();
                double overchargedQtyBasicUnit = itemDTO.getOverchargedQtyBasicUnit();
                double underchargedQtyBasicUnit = itemDTO.getUnderchargedQtyBasicUnit();
                if (overchargedQtyBasicUnit > 0 || underchargedQtyBasicUnit > 0){
                    Map<String, Object> itemMaterialInfo = this.baseMapper.itemInfo(sapDn, sapDnItem);
                    Map<String, Object> map = new HashMap<>();
                    map.put("xh", String.valueOf(j));
                    map.put("wlid", itemMaterialInfo.get("materialNo"));
                    map.put("wltext", itemMaterialInfo.get("materialZhDesc"));
                    map.put("wlunit", itemMaterialInfo.get("basicUnit"));

                    /** 少收基本单位数量大于0，则按出库类型 0 收货短少处理 */
                    if (underchargedQtyBasicUnit > 0){
                        map.put("wlquantity", underchargedQtyBasicUnit);
                        map.put("stocktype", 0);
                    }

                    /** 多收基本单位数量大于0，则按出库类型 1 收货多出处理 */
                    if (overchargedQtyBasicUnit > 0){
                        map.put("wlquantity", overchargedQtyBasicUnit);
                        map.put("stocktype", 1);
                    }
                    map.put("area", "");
                    map.put("colorno", itemMaterialInfo.get("colorNo"));
                    map.put("causeofbroken", itemDTO.getRemarks());
                    mapList.add(map);
                }
            }

            DetailTableInfo dtsInfo = new DetailTableInfo();
            //表示只有 1 个明细表
            DetailTable[] dts = new DetailTable[1];
            dts[0] = new DetailTable();
            dts[0].setId("1");
            Row[] rows = new Row[mapList.size()];
            for (int k = 0; k < mapList.size(); k ++){
                Map<String, Object> item = mapList.get(k);
                rows[k] = new Row();
                rows[k].setId(String.valueOf(k));
                Cell[] cl = {new Cell(), new Cell(), new Cell(), new Cell(), new Cell(), new Cell(), new Cell(), new Cell(), new Cell()};
                int x = 0;
                for (Map.Entry<String, Object> entry : item.entrySet()){
                    cl[x].setName(entry.getKey());
                    cl[x].setValue(entry.getValue() == null ? "" : entry.getValue().toString());
                    x ++;
                }
                rows[k].setCell(cl);
            }
            dts[0].setRow(rows);
            dtsInfo.setDetailTable(dts);

            reqinfo.setMainTableInfo(wmi);
            reqinfo.setDetailTableInfo(dtsInfo);

            log.info("==========海外收货损益提交OA reqinfo==========\n" + JSON.toJSONString(reqinfo));

            // 生成待办 ，返回待办id
            int reqid = Integer.parseInt(wfproxy.createRequest(reqinfo));
            // 返回大于0 的数字则调用成功
            log.info("==========交货单损益结果提交OA审批，返回 reqid:" + reqid);
            if (reqid > 0){
                iOverseaOperateLogService.addOverseaOperateLog(spmsUser.getUserId(), sapDeliveryNote, OVERSEA_DN_SUBMIT_OA.getDescZh(),
                        OVERSEA_DN_SUBMIT_OA.getDescEn(), oaLog, JSON.toJSONString(reqinfo), String.valueOf(reqid), "");
            } else {
                iOverseaOperateLogService.addOverseaOperateLog(spmsUser.getUserId(), sapDeliveryNote, OVERSEA_DN_SUBMIT_OA_ERROR.getDescZh(),
                        OVERSEA_DN_SUBMIT_OA_ERROR.getDescEn(), oaLog, JSON.toJSONString(reqinfo), String.valueOf(reqid), "");
            }
            return reqid;
        } catch (RemoteException remoteException){
            remoteException.printStackTrace();
            log.info("=========交货单损益提交OA连接错误=========" + remoteException.getMessage());
            return 0;
        } catch (Exception e){
            e.printStackTrace();
            log.error("========交货单损益信息请求参数：" + overseaDeliveryNoteOaDTO.toString() + "\n请求提交OA异常=========\n" + e.getMessage());
            return 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult closeOverseaDeliveryNote(String sapDeliveryNote, Integer dataVersion, String userId) {
        try {
            if (StringUtils.isEmpty(sapDeliveryNote) || dataVersion == null){
                return ResponseResult.error("请求参数错误");
            }
            OverseaDeliveryNote overseaDeliveryNote = getOverseaDn(sapDeliveryNote);
            if (overseaDeliveryNote == null){
                return ResponseResult.error("请求交货单信息不存在");
            }
            if (!dataVersion.equals(overseaDeliveryNote.getDataVersion())){
                return ResponseResult.error("请求数据已更新请刷新后重试");
            }
            String spmsStatus = overseaDeliveryNote.getSpmsStatus();
            if (!OVERSEA_DN_WAITING.getCode().equals(spmsStatus)){
                return ResponseResult.error("交货单当前状态禁止此操作");
            }
            overseaDeliveryNote.setSpmsStatus(OVERSEA_DN_DELETE.getCode());
            overseaDeliveryNote.setDataStatus(DATA_STATUS_1);
            this.baseMapper.update(overseaDeliveryNote, new QueryWrapper<OverseaDeliveryNote>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote));

            QueryWrapper<OverseaDeliveryNoteDtl> queryWrapper = new QueryWrapper<OverseaDeliveryNoteDtl>().eq("SAP_DELIVERY_NOTE", sapDeliveryNote);
            OverseaDeliveryNoteDtl overseaDeliveryNoteDtl = new OverseaDeliveryNoteDtl();
            overseaDeliveryNoteDtl.setDataStatus(DATA_STATUS_1);
            iOverseaDeliveryNoteDtlService.update(overseaDeliveryNoteDtl, queryWrapper);

            iOverseaOperateLogService.addOverseaOperateLog(userId, sapDeliveryNote, OVERSEA_DN_DELETE.getDescZh(), OVERSEA_DN_DELETE.getDescEn(), "");

            return ResponseResult.success("交货单关闭成功")
                    .add("overseaDeliveryNote", getOverseaDnHead(sapDeliveryNote));
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("交货单关闭错误 Exception").add("error", e.getMessage());
        }
    }


    @Override
    public List<Map<String, Object>> getOverdueDeliveryNote(String werks) {
        return this.baseMapper.getOverdueDeliveryNote(werks);
    }
}
